package com.shiro.test.mvc.service.impl;

import com.shiro.test.mvc.dao.IBaseDao;
import com.shiro.test.mvc.mapper.LeaveApplyMapper;
import com.shiro.test.mvc.mapper.UserMapper;
import com.shiro.test.mvc.pojo.Dept;
import com.shiro.test.mvc.pojo.LeaveApply;
import com.shiro.test.mvc.pojo.User;
import com.shiro.test.mvc.service.ILeaveApplyService;
import com.shiro.test.mvc.service.IUserService;
import com.shiro.test.mvc.util.Constants;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by Administrator on 2020/11/26 0026.
 */
@Service
public class LeaveApplyServiceImpl extends BaseServiceImpl<LeaveApply> implements ILeaveApplyService{

    @Autowired
    private LeaveApplyMapper leaveApplyMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;
    
    @Autowired
    private HistoryService historyService;

    @Autowired
    private RepositoryService repositoryService;

    @Override
    public IBaseDao<LeaveApply> getDao() {
        return leaveApplyMapper;
    }

    @Override
    public void addLeaveApply(LeaveApply leaveApply) {
        leaveApply.setStatus(Constants.LEAVE_STATUS_CREATE);
        leaveApplyMapper.addLeaveApply(leaveApply);
        Map<String,Object> variable = new HashMap<>();
        variable.put("userId",leaveApply.getUser().getId());
        runtimeService.startProcessInstanceByKey(Constants.LEAVE_TIPS,leaveApply.getId().toString(),variable);

        //查询处理人
        List<Integer> assignIds = userMapper.getAssignUsers(leaveApply.getUser());

        Task task = taskService.createTaskQuery()
                    .taskAssignee(leaveApply.getUser().getId().toString())//设置申请提交人
                    .processDefinitionKey(Constants.LEAVE_TIPS)
                    .processInstanceBusinessKey(leaveApply.getId().toString()).singleResult();
        variable.put("adminIds", StringUtils.join(assignIds.iterator(),","));
        taskService.complete(task.getId(),variable);
    }

    @Override
    public List<LeaveApply> getLeaveList(LeaveApply criteria) {
        return leaveApplyMapper.getLeaveList(criteria);
    }

    @Override
    public List<LeaveApply> getLeaveTaskList(int userId) {
        return leaveApplyMapper.getLeaveTaskList(userId);
    }

    @Override
    public void updateLeave(LeaveApply leaveApply) {
        leaveApplyMapper.updateLeave(leaveApply);
    }

    @Override
    public void updateTask(LeaveApply leaveApply, Integer userId) {
        Task task = taskService.createTaskQuery()
                .taskCandidateUser(userId.toString())//设置任务处理人
                .processDefinitionKey(Constants.LEAVE_TIPS)
                .processInstanceBusinessKey(leaveApply.getId().toString()).singleResult();
        Map<String,Object> variable = new HashMap<>();
        variable.put("advice",leaveApply.getStatus());
        if (leaveApply.getStatus().equals(Constants.LEAVE_STATUS_REJECT)){//驳回
            //驳回任务
            rejectProcess(task.getId());
        }else{
            User user = new User();
            Dept dept = new Dept();
            dept.setId(4);
            user.setDept(dept);
            List<Integer> assignIds = userMapper.getAssignUsers(user);
            variable.put("hrIds",StringUtils.join(assignIds.iterator(),","));
            taskService.complete(task.getId(),variable);
        }
        updateLeave(leaveApply);
    }

    //驳回上一步操作
    private void rejectProcess(String taskId){
        //获取当前任务
        HistoricTaskInstance curTask = historyService.createHistoricTaskInstanceQuery()
                            .taskId(taskId).singleResult();
        //获取流程实例
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                            .includeProcessVariables()//声明搜索引擎需要查询流程参数
                            .processInstanceId(curTask.getProcessInstanceId()).singleResult();
        if (instance == null) {
            System.out.println("流程结束");
            System.out.println("出错啦！流程已经结束");
            return ;
        }
        //获得实例中的参数
        Map<String, Object> variables = instance.getProcessVariables();
        //获取流程定义
        ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService)
                            .getDeployedProcessDefinition(curTask.getProcessDefinitionId());
        if (definition == null) {
            System.out.println("流程定义未找到");
            System.out.println("出错啦！流程定义未找到");
            return;
        }
        //当前的活动
        ActivityImpl curActivity = definition.findActivity(curTask.getTaskDefinitionKey());
        //当前活动的入口
        List<PvmTransition> nextTransitions = curActivity.getIncomingTransitions();
        
        //清除当前活动的出口
        List<PvmTransition> bakPvmTransitions = new ArrayList<>();
        List<PvmTransition> curPvmTransitions = curActivity.getOutgoingTransitions();
        for (PvmTransition curPvmTransition : curPvmTransitions) {
            bakPvmTransitions.add(curPvmTransition);
        }
        curPvmTransitions.clear();

        //建立新出口
        List<TransitionImpl> newTransitions = new ArrayList<>();
        for (PvmTransition nextTransition : nextTransitions) {
            PvmActivity nextActivity = nextTransition.getSource();
            ActivityImpl nextActivityImpl = definition.findActivity(nextActivity.getId());
            TransitionImpl newTransition = curActivity.createOutgoingTransition();
            newTransition.setDestination(nextActivityImpl);
            newTransitions.add(newTransition);

        }
        //完成任务
        String insId = instance.getId();
        String defKey = curTask.getTaskDefinitionKey();
        List<Task> tasks = taskService.createTaskQuery()
                                .processInstanceId(insId).taskDefinitionKey(defKey).list();
        for (Task task : tasks) {
            taskService.complete(task.getId(),variables);
            historyService.deleteHistoricTaskInstance(task.getId());
        }
        
        //恢复执行方向
        for (TransitionImpl newTransition : newTransitions) {
            curActivity.getOutgoingTransitions().remove(newTransition);
        }
        for (PvmTransition bakPvmTransition : bakPvmTransitions) {
            curPvmTransitions.add(bakPvmTransition);
        }
    }

    @Override
    public void updateTaskResubmit(LeaveApply leaveApply) {
        Task task = taskService.createTaskQuery()
                    .taskAssignee(leaveApply.getUser().getId().toString())
                    .processDefinitionKey(Constants.LEAVE_TIPS)
                    .processInstanceBusinessKey(leaveApply.getId().toString()).singleResult();
        taskService.complete(task.getId());
        leaveApply.setStatus(Constants.LEAVE_STATUS_CREATE);
        updateLeave(leaveApply);

    }
}
